package com.itheima.stock.service.impl;

import com.google.common.base.Strings;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.res.LoginRespVo;
import com.itheima.stock.vo.res.R;
import com.itheima.stock.vo.res.ResponseCode;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

//定义用户服务接口实现

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Override
    public R<LoginRespVo> login(LoginReqVo vo) {
        //1判断传入参数的合法性
        if (vo == null || Strings.isNullOrEmpty(vo.getUsername()) ||
                Strings.isNullOrEmpty(vo.getPassword()) ||
                Strings.isNullOrEmpty(vo.getRkey()) ||
                Strings.isNullOrEmpty(vo.getCode())) {
            //请求参数异常
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //根据传入的rkey 从redis中获取保存的验证码，然后与传入的验证码进行比对
        String rCode = (String) redisTemplate.opsForValue().get("ck:"+vo.getRkey());
        if (rCode == null || ! rCode.equals(vo.getCode())) {
            //请求参数异常
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //及时淘汰传入的数据  当然也可以借助失效周期 自动淘汰
        redisTemplate.delete("ck:"+vo.getRkey());
        //2.根据用户查询用户信息 含加密后的密文
        SysUser userInfo = sysUserMapper.findUserByUserName(vo.getUsername());
        //3.判断对应用户是否存在，以及密码是否匹配
        if (userInfo==null || ! passwordEncoder.matches(vo.getPassword(),userInfo.getPassword())) {
            return R.error(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage());
        }
        //4.将查询的用户信息封装到LoginRespVo类型的对象下
        //我们发现查询对象中含响应数据 但不能直接返回1.不安全 2.浪费网络资源 按需加载
        LoginRespVo loginRespVo = new LoginRespVo();
//        loginRespVo.setId(userInfo.getId());
        BeanUtils.copyProperties(userInfo,loginRespVo);
        //5.组装响应对象 响应前端
        return R.ok(loginRespVo);
    }


    //生成登录验证码
    @Override
    public R<Map> generateCode() {
        //1.生成随机码 长度为4 且都为数字
        //借助Apach提供的工具类 生成纯数字字符串
        String checkCode = RandomStringUtils.randomNumeric(4);
        //2.生成全局唯一的 id ，模拟session
        String sessionId = String.valueOf(idWorker.nextId());
        //3.保存在redis中 设置失效时间 1min
        //id加前缀的业务码 方便阅读 维护
        redisTemplate.opsForValue().set("ck:"+sessionId,checkCode,5, TimeUnit.MINUTES);
        //4.组装数据 响应前端
        Map<String, String> map = new HashMap<>();
        map.put("code", checkCode);
        map.put("rkey",sessionId);
        return R.ok(map);
    }
}
